import java.util.ArrayList;
import java.util.List;
import java.math.*;
import java.util.Date;
import java.text.SimpleDateFormat;
/**
 * Created by ospip on 2017/9/25.
 * Copyright (c) 2017 LLAP. All rights reserved.
 */
public class BankAccount {
    private class Balance {
        public double CNY;
        public double USD;

        public Balance() {
            CNY = USD = 0;
        }

        public void add(String type, double inc) {
            switch(type) {
                case "CNY":
                    this.CNY += inc;
                    break;
                case "USD":
                    this.USD += inc;
                    break;
            }
        }

        public double get(String type) {
            switch (type) {
                case "CNY":
                    return this.CNY;
                case "USD":
                    return this.USD;
            }
            return -1;
        }
    }
    public String type = "Normal Account";
    public String cardID;
    public String identity;
    public int expireMonth;
    public int expireYear;
    public String cardHolder;
    public int CVV2;
    public Balance balance;
    public String[] currencyType = {"CNY", "USD"};
    private static double interestRate = 0.0001;
    public List<String> logList;
    public boolean available = true;

    public BankAccount(String cardID, String cardHolder, String identity, int expireMonth, int expireYear, int CVV2) {
        this.cardID = cardID;
        this.cardHolder = cardHolder;
        this.identity = identity;
        this.expireMonth = expireMonth;
        this.expireYear = expireYear;
        this.CVV2 = CVV2;
        this.balance = new Balance();
        logList = new ArrayList<>();
        this.log("Account created");
    }

    public void log(String message, String level) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        logList.add("[" + df.format(new Date()) + "][" + level + "]" + message);
    }
    public void log(String message) { this.log(message, "INFO"); }

    public void addBalance(String type, double b) {
        this.balance.add(type, b);
        log(type + ", " + (b >= 0?"+" + b : b), "BALANCE");
    }

    public boolean transaction(BankAccount acc, String type, double inc) {
        if (inc <= 0) return false;
        if (this.balance.get(type) < inc) return false;
        this.log(acc.cardID + ", " + type + ", " + inc, "TRANSACTION");
        this.addBalance(type, -inc);
        acc.addBalance(type, inc);
        acc.log("RECEIVED FROM " + this.cardID + ", " + type + ", " + inc, "TRANSACTION");
        return true;
    }

    public boolean deposit(String type, double amount) {
        if (this.balance.get(type) < amount) return false;
        log(type + " " + amount, "DEPOSIT");
        this.addBalance(type, -amount);

        return true;
    }

    public void addInterest(double interestRate) {
        for (String type : currencyType) {
            this.addBalance(type, this.balance.get(type) * interestRate);
            log(type + " + " + this.balance.get(type) * interestRate, "INC");
        }
    }

    public void addInterest() {
        this.addInterest(BankAccount.interestRate);
    }

    public boolean cancel() {
        this.available = false;
        return true;
    }

    @Override
    public String toString() {
        return "<BankAccount " + this.cardID + (available ? "" : " (Closed)") + ">";
    }

    public String query(int verbose) {
        String ret = "";
        switch (verbose) {
            case 6:
                ret += "<Log>\n";
                for (String t : logList) {
                    ret += "    " + t + "\n";
                }
                ret += "</Log>\n";
            case 5:
                ret = "Cardholder Identity: " + identity + "\n" + ret;
            case 4:
                ret = "CVV2: " + CVV2 + "\n" + ret;
            case 3:
                ret = "Expire Date: " + String.format("%02d/%02d", expireMonth, expireYear) + "\n" + ret;
            case 2:
                ret = "Card Holder: " + cardHolder + "\n" + ret;
            case 1:
                for (String type : currencyType) {
                    ret = type + " Account Balance: " + this.balance.get(type) + "\n" + ret;
                }
                ret = "Type: " + this.type + "\n" + ret;
        }
        return this.toString() + "\n" + ret + "</BankAccount Verbose " + verbose + ">";
    }

    public static void main(String[] args) {
        BankAccount acc = new BankAccount("6222021108001015676", "JOHN DOE", "321000200011110123", 6, 22, 967);
        acc.addBalance("CNY", 15040);
        acc.addBalance("USD", 3000);
        acc.addInterest();
        acc.deposit("CNY", 300);
        System.out.println(acc.query(6));
        acc.cancel();
        System.out.println(acc);
    }
}
